#pragma once

#include <imglib/bitmap.h>
#include <imglib/imageclass_decl.h>
#include <mswin/timing.h>
#include "types.h"

namespace trm {

namespace mincut {

typedef img::bitmap mask;
typedef mono_byte_image gray_mask;

typedef unsigned int uint;

struct params {
	params() {
		pyramid_levels = 2;
		max_motion = 2; //real max motion is nearly 2*2^2 = 8
		hw = 5;
		nn = 5;
		aspect = 10;
		interframe_hw = 5;
		interframe_nn = 5;
		interframe_pyramid_levels = 2;
		source = source_both;
		gray_levels_exp = 0;
		silent = false;
		timing_tree = 0;
	}
	// algorihm parameters
	uint pyramid_levels; ///< 0..5, 0 means no usage of downsampled images
	uint max_motion; ///< how thick is the area of uncertainty around mask border on each pyramid level (except for the highest level for segment(...))
	size_t hw; ///< half window size
	size_t nn; ///< the number of nearest neighbours, edges from each pixel
	float aspect; ///< color/distance aspect ratio = sigma_color^2/sigma_distance^2
	// many frames parameters
	size_t interframe_hw;
	size_t interframe_nn;
	uint interframe_pyramid_levels; ///< determines how many initial pyramid levels to use multiple images,
		///< for levels (pyramid_levels - interframe_pyramid_levels) ... 0 the program will work in single image mode
	information_source source;
	// antializing
	uint gray_levels_exp;	///< the more the value the more levels you will see on resulting image;
							///< their exact number is 2^(gray_levels_exp+2) - 1;
							///< the value 0 do not really perform antializing but only shows ambiguous areas with gray color
	// other parameters
	bool silent; ///< prints nothing in std::clog if true
	mswin::timing_tree * timing_tree;
};

/// segmentation in 1 frame
void segment(
	byte_image const & image,
	mask const & obligatory_foreground_pixels,
	mask const & obligatory_background_pixels,
	mask * foreground_only, ///< zero pixels are either belong to background or undetermined ones
	mask * background_only, ///< zero pixels are either belong to foreground or undetermined ones
	params const & p = params(),
	gray_mask * gmask = 0);		///< output grey mask

/// this function constructs obligatory masks by eroding and dilating
/// initial foreground mask on given number of pixels (max motion)
void adjust(
	byte_image const & image,
	mask const & initial_foreground_mask,
	mask * foreground_only,
	mask * background_only,
	params const & p = params(),
	gray_mask * gmask = 0);

/// segmentation of image taking as an example given segmentation (mask) of reference image
void track(
	byte_image const & ref_image,
	mask const & ref_mask,
	byte_image const & image,
	mask * foreground_only,
	mask * background_only,
	params const & p = params(),
	gray_mask * gmask = 0);

/// selects between adjust(...) and track(...) based on 'source' parameter
void run(
	byte_image const & ref_image,
	mask const & ref_mask,
	byte_image const & image,
	mask * foreground_only,
	mask * background_only,
	params const & p = params(),
	gray_mask * gmask = 0);

} //mincut

} //param
